大家應該都還記得,Ruby是一款物件導向程式語言(Objecte-Oriented Programming, OOP),所以在Ruby裡幾乎什麼東西都是物件。但也有少數例外例子,像是Block就不是一個物件,因此Block沒有辦法單獨存在,所以單獨執行會出現錯誤。
{ puts "Hello" } # SyntaxError
action = { puts "Hello" } # SyntaxError
Block使用時需要接在方法後面
但是Block本身也不是參數
我們會在程式碼看到 do ... end
以及 {}
的寫法就是我們所說的Block
在Ruby會利用Block來傳遞方法,在方法裡的會在兩個 |
之間來定義參數,舉例來說大概長這樣:
do … end 的寫法
通常建議多行程式碼得時候使用do ... end
[1, 2, 3].each do | num |
puts num
End
大括號 { } 的寫法
則只有單行程式碼時才會使用{}
,可讓語法看起來精簡
[1, 2, 3].each { | num | puts num }
所以當我們在Block裡看到 |num|
這樣定義的參數是一個區域變數,它只能活在Block範圍裡,一旦離開Block之後就會失效。
要讓Block執行內容,可使用yield方法調用block
使用yield暫時把控制權交棒給Block,等Block執行結束後再把控制權交回來。
def hi_yield
puts "= start ="
yield # 暫時交棒給Block
puts "= end ="
end
hi_yield { puts "Hello" }
# = start =
# Hello
# = end =
yield方法將轉控制權給Block的時候,也可以順便把值帶給Block。
def hi_yield
puts "= start ="
yield 123 # 暫時交棒給Block,並且傳數字123給Block
puts "= end ="
end
say_hello { |x|
puts "hi,這裡是 Block,我拿到 #{x} 囉!" # |x|會收到來自yield得值123
}
# = start =
# hi,這裡是 Block,我拿到 123 囉!
# = end =
有一種狀況是方法實作裡面有yield,但是呼叫方法的時候卻沒有block,此時執行方法有錯誤訊息”no block given (yield) (LocalJumpError)”。
在這種狀況要讓方法在呼叫的時候也能正常執行,我們可以在yield那邊加入一個條件式判斷 if block_given?
def hi_block
if block_given?
yield
else
"no block"
end
end
hi_block # => "no block"
hi_block { "hello" } # => "hello"
hi_block do "hello" end # => "hello"
參考連結:
為你自己學 Ruby on Rails
談談Ruby中的block